package com.physics.mps.module.util;

import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.physics.mps.common.exception.BusinessException;
import com.physics.mps.common.util.AssertUtil;
import com.physics.mps.common.util.OkHttpUtil;
import com.physics.mps.entity.enums.CodeEnum;
import com.physics.mps.entity.vo.*;
import com.physics.mps.entity.vo.*;
import com.physics.mps.entity.vo.result.AbaqusEmagParam;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.*;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.*;


/**
 * Json解析器
 *
 * @author mcsoft
 * @since 2023/9/21
 */
@Component
@Log4j2
public class JsonResolver {
    @Value("${simulate.abaqus.stp-path}")
    private String stpDir;

    Map<String, AbaqusPartVo> paramPart;

    int partNum;

    AbaqusMeshVo meshVo;

    AbaqusJobVo jobVo;

    Map<String, InteractionVo> interactions;

    Map<String, TemperatureFieldVo> fields;

    Map<String, Map<String, List<List<String>>>> materials;

    String defaultMaterial;

    Map<String, AbaqusBoundaryVo> boundaries;

    Map<String, AbaqusBodyHeatFluxVo> bodyHeatFluxes;

    Map<String, AbaqusTieVo> ties;

    StringBuilder initTemperature;

    StringBuilder stpPath;

    String stpName;

    String board;

    List<String> freq;

    List<String> directDamping;

    List<String> spectrumDensity;

    List<String> frequency;

    public JsonResolver() {
        paramPart = new HashMap<>();
        partNum = 0;
        meshVo = new AbaqusMeshVo();
        jobVo = new AbaqusJobVo();
        interactions = new HashMap<>();
        fields = new HashMap<>();
        materials = new HashMap<>();
        defaultMaterial = "";
        boundaries = new HashMap<>();
        bodyHeatFluxes = new HashMap<>();
        ties = new HashMap<>();
        initTemperature = new StringBuilder();
        stpPath = new StringBuilder();
        stpName = "";
        board = "";
        freq = new ArrayList<>();
        directDamping = new ArrayList<>();
        spectrumDensity = new ArrayList<>();
        frequency = new ArrayList<>();
    }


    public AbaqusHeatTransferParam jsonParseToAbaqusHeatTransferParam(String jsonPath, Integer type) {
        formattingResolver();

        Map<String, Object> params;
        if (type == 1) {
            params = JSONUtil.toBean(jsonPath, LinkedHashMap.class);
        } else {
            params = jsonMap(jsonPath);
        }


        AbaqusHeatTransferStepVo stepVo = new AbaqusHeatTransferStepVo();

        params.forEach((name, value) -> {
            try {
                checkParamModule(name, value);
                if (name.matches("STEP_.*")) {
                    storeHeatTransferStep(name, value, stepVo);
                }
            } catch (Exception e) {
                log.info(String.format("Error Parameter: name=%s, value=%s", name, value));
            }
        });
        AbaqusHeatTransferParam abaqusHeatTransferParam = new AbaqusHeatTransferParam();

        abaqusHeatTransferParam.setMeshVo(meshVo);
        if (jobVo.getNumDomain() % jobVo.getNumCpus() != 0) {
            throw new BusinessException(CodeEnum.DATA_DOMAIN_ERROR);
        }
        abaqusHeatTransferParam.setJobVo(jobVo);
        if (Float.valueOf(stepVo.getInitialInc()) > Float.valueOf(stepVo.getTimePeriod())) {
            throw new BusinessException(CodeEnum.INITIAL_INCREMENT_TIME_PERIOD_ERROR);
        }
        abaqusHeatTransferParam.setHeatTransferStepVo(stepVo);
        abaqusHeatTransferParam.setPartNames(paramPart.keySet());

        if (paramPart.size() < partNum) {
            //throw new BusinessException(CodeEnum.PART_LACK);
            defaultMaterial();
        }
        List<AbaqusPartVo> parts = new ArrayList<>();
        paramPart.forEach((name, value) -> {
            parts.add(value);
        });
        abaqusHeatTransferParam.setParts(parts);

        List<InteractionVo> interactionVos = new ArrayList<>();
        interactions.forEach((name, value) -> {
            interactionVos.add(value);
        });
        abaqusHeatTransferParam.setInteractions(interactionVos);

        List<TemperatureFieldVo> fieldVos = new ArrayList<>();
        fields.forEach((name, value) -> {
            fieldVos.add(value);
        });
        abaqusHeatTransferParam.setTemperatureFieldVos(fieldVos);

        List<AbaqusTieVo> tieVos = new ArrayList<>();
        ties.forEach((name, value) -> {
            tieVos.add(value);
        });
        abaqusHeatTransferParam.setTieVos(tieVos);

        abaqusHeatTransferParam.setStpPath(stpPath.toString());
        abaqusHeatTransferParam.setStpName(stpName);
        abaqusHeatTransferParam.setBoard(board);
        return abaqusHeatTransferParam;
    }

    public AbaqusRandomVibrationParam jsonParseToAbaqusRandomVibrationParam(String jsonPath, Integer type) {
        formattingResolver();

        Map<String, Object> params;
        if (type == 1) {
            params = JSONUtil.toBean(jsonPath, LinkedHashMap.class);
        } else {
            params = jsonMap(jsonPath);
        }

        AbaqusRandomVibrationStepVo stepVo = new AbaqusRandomVibrationStepVo();

        params.forEach((name, value) -> {
            try {
                checkParamModule(name, value);
                if (name.matches("STEP_.*")) {
                    storeRandomVibrationStep(name, value, stepVo);
                }
            } catch (Exception e) {
                log.info(String.format("Error Parameter: name=%s, value=%s", name, value));
            }
        });

        stepVo.setFreq(listToString(freq));
        stepVo.setDirectDamping(listToString(directDamping));
        stepVo.setData(createData());

        AbaqusRandomVibrationParam randomVibrationParam = new AbaqusRandomVibrationParam();

        randomVibrationParam.setMeshVo(meshVo);
        randomVibrationParam.setJobVo(jobVo);
        randomVibrationParam.setRandomVibrationStepVo(stepVo);
        randomVibrationParam.setPartNames(paramPart.keySet());

        if (paramPart.size() < partNum) {
            //throw new BusinessException(CodeEnum.PART_LACK);
            defaultMaterial();
        }
        List<AbaqusPartVo> parts = new ArrayList<>();
        paramPart.forEach((name, value) -> {
            parts.add(value);
        });
        randomVibrationParam.setParts(parts);

        List<AbaqusBoundaryVo> boundaryVos = new ArrayList<>();
        boundaries.forEach((name, value) -> {
            boundaryVos.add(value);
        });
        randomVibrationParam.setBoundaryVos(boundaryVos);

        List<AbaqusTieVo> tieVos = new ArrayList<>();
        ties.forEach((name, value) -> {
            tieVos.add(value);
        });
        randomVibrationParam.setTieVos(tieVos);

        randomVibrationParam.setStpPath(stpPath.toString());
        randomVibrationParam.setStpName(stpName);
        randomVibrationParam.setBoard(board);
        return randomVibrationParam;
    }

    public AbaqusRandomVibrationParam jsonParseToAbaqusHarmonicResponseParam(String jsonPath, Integer type) {
        formattingResolver();

        Map<String, Object> params;
        if (type == 1) {
            params = JSONUtil.toBean(jsonPath, LinkedHashMap.class);
        } else {
            params = jsonMap(jsonPath);
        }

        AbaqusRandomVibrationStepVo stepVo = new AbaqusRandomVibrationStepVo();

        params.forEach((name, value) -> {
            try {
                checkParamModule(name, value);
                if (name.matches("STEP_.*")) {
                    storeRandomVibrationStep(name, value, stepVo);
                }
            } catch (Exception e) {
                log.info(String.format("Error Parameter: name=%s, value=%s", name, value));
            }
        });

        stepVo.setFreq(listToString(freq));
        stepVo.setDirectDamping(listToString(directDamping));
        stepVo.setData(createData2());

        AbaqusRandomVibrationParam randomVibrationParam = new AbaqusRandomVibrationParam();

        randomVibrationParam.setMeshVo(meshVo);
        randomVibrationParam.setJobVo(jobVo);
        randomVibrationParam.setRandomVibrationStepVo(stepVo);
        randomVibrationParam.setPartNames(paramPart.keySet());

        if (paramPart.size() < partNum) {
            //throw new BusinessException(CodeEnum.PART_LACK);
            defaultMaterial();
        }
        List<AbaqusPartVo> parts = new ArrayList<>();
        paramPart.forEach((name, value) -> {
            parts.add(value);
        });
        randomVibrationParam.setParts(parts);

        List<AbaqusBoundaryVo> boundaryVos = new ArrayList<>();
        boundaries.forEach((name, value) -> {
            boundaryVos.add(value);
        });
        randomVibrationParam.setBoundaryVos(boundaryVos);

        List<AbaqusTieVo> tieVos = new ArrayList<>();
        ties.forEach((name, value) -> {
            tieVos.add(value);
        });
        randomVibrationParam.setTieVos(tieVos);

        randomVibrationParam.setStpPath(stpPath.toString());
        randomVibrationParam.setStpName(stpName);
        randomVibrationParam.setBoard(board);
        return randomVibrationParam;
    }

    public AbaqusCoupledThermalElectricParam jsonParseToAbaqusCoupledThermalElectricParam(String jsonPath, Integer type) {
        formattingResolver();

        Map<String, Object> params;
        if (type == 1) {
            params = JSONUtil.toBean(jsonPath, LinkedHashMap.class);
        } else {
            params = jsonMap(jsonPath);
        }

        AbaqusCoupledThermalElectricStepVo stepVo = new AbaqusCoupledThermalElectricStepVo();

        params.forEach((name, value) -> {
            try {
                checkParamModule(name, value);
                if (name.matches("STEP_.*")) {
                    storeCoupledThermalElectricStep(name, value, stepVo);
                }
            } catch (Exception e) {
                log.info(String.format("Error Parameter: name=%s, value=%s", name, value));
            }
        });
        AbaqusCoupledThermalElectricParam coupledThermalElectricParam = new AbaqusCoupledThermalElectricParam();

        coupledThermalElectricParam.setMeshVo(meshVo);
        coupledThermalElectricParam.setJobVo(jobVo);
        coupledThermalElectricParam.setCoupledThermalElectricStepVo(stepVo);
        coupledThermalElectricParam.setPartNames(paramPart.keySet());

        if (paramPart.size() < partNum) {
            //throw new BusinessException(CodeEnum.PART_LACK);
            defaultMaterial();
        }
        List<AbaqusPartVo> parts = new ArrayList<>();
        paramPart.forEach((name, value) -> {
            parts.add(value);
        });
        coupledThermalElectricParam.setParts(parts);

        List<InteractionVo> interactionVos = new ArrayList<>();
        interactions.forEach((name, value) -> {
            interactionVos.add(value);
        });
        coupledThermalElectricParam.setInteractions(interactionVos);

        List<TemperatureFieldVo> fieldVos = new ArrayList<>();
        fields.forEach((name, value) -> {
            fieldVos.add(value);
        });
        coupledThermalElectricParam.setTemperatureFieldVos(fieldVos);

        List<AbaqusTieVo> tieVos = new ArrayList<>();
        ties.forEach((name, value) -> {
            tieVos.add(value);
        });
        coupledThermalElectricParam.setTieVos(tieVos);

        List<AbaqusBoundaryVo> boundaryVos = new ArrayList<>();
        boundaries.forEach((name, value) -> {
            boundaryVos.add(value);
        });
        coupledThermalElectricParam.setBoundaryVos(boundaryVos);

        coupledThermalElectricParam.setInitTemperature(initTemperature.toString());

        coupledThermalElectricParam.setStpPath(stpPath.toString());
        coupledThermalElectricParam.setStpName(stpName);
        coupledThermalElectricParam.setBoard(board);
        return coupledThermalElectricParam;
    }

    public AbaqusCoupledTempDisplacementParam jsonParseToAbaqusCoupledTempDisplacementParam(String jsonPath, Integer type) {
        formattingResolver();

        Map<String, Object> params;
        if (type == 1) {
            params = JSONUtil.toBean(jsonPath, LinkedHashMap.class);
        } else {
            params = jsonMap(jsonPath);
        }

        AbaqusCoupledTempDisplacementStepVo stepVo = new AbaqusCoupledTempDisplacementStepVo();

        params.forEach((name, value) -> {
            try {
                checkParamModule(name, value);
                if (name.matches("STEP_.*")) {
                    storeCoupledTempDisplacementStep(name, value, stepVo);
                }
            } catch (Exception e) {
                log.info(String.format("Error Parameter: name=%s, value=%s", name, value));
            }
        });

        AbaqusCoupledTempDisplacementParam coupledTempDisplacementParam = new AbaqusCoupledTempDisplacementParam();
        coupledTempDisplacementParam.setMeshVo(meshVo);
        coupledTempDisplacementParam.setJobVo(jobVo);
        coupledTempDisplacementParam.setTempDisplacementStepVo(stepVo);
        coupledTempDisplacementParam.setPartNames(paramPart.keySet());

        if (paramPart.size() < partNum) {
            //throw new BusinessException(CodeEnum.PART_LACK);
            defaultMaterial();
        }
        List<AbaqusPartVo> parts = new ArrayList<>();
        paramPart.forEach((name, value) -> {
            parts.add(value);
        });
        coupledTempDisplacementParam.setParts(parts);

        List<InteractionVo> interactionVos = new ArrayList<>();
        interactions.forEach((name, value) -> {
            interactionVos.add(value);
        });
        coupledTempDisplacementParam.setInteractions(interactionVos);

        List<TemperatureFieldVo> fieldVos = new ArrayList<>();
        fields.forEach((name, value) -> {
            fieldVos.add(value);
        });
        coupledTempDisplacementParam.setTemperatureFieldVos(fieldVos);

        List<AbaqusTieVo> tieVos = new ArrayList<>();
        ties.forEach((name, value) -> {
            tieVos.add(value);
        });
        coupledTempDisplacementParam.setTieVos(tieVos);

        List<AbaqusBoundaryVo> boundaryVos = new ArrayList<>();
        boundaries.forEach((name, value) -> {
            boundaryVos.add(value);
        });
        coupledTempDisplacementParam.setBoundaryVos(boundaryVos);

        coupledTempDisplacementParam.setInitTemperature(initTemperature.toString());

        List<AbaqusBodyHeatFluxVo> bodyHeatFluxVos = new ArrayList<>();
        bodyHeatFluxes.forEach((name, value) -> {
            bodyHeatFluxVos.add(value);
        });
        coupledTempDisplacementParam.setBodyHeatFluxesVos(bodyHeatFluxVos);

        coupledTempDisplacementParam.setStpPath(stpPath.toString());
        coupledTempDisplacementParam.setStpName(stpName);
        coupledTempDisplacementParam.setBoard(board);
        return coupledTempDisplacementParam;
    }

    public AbaqusEmagParam jsonParseToAbaqusEmagParam(String jsonPath, Integer type) {
        formattingResolver();

        Map<String, Object> params;
        if (type == 1) {
            params = JSONUtil.toBean(jsonPath, LinkedHashMap.class);
        } else {
            params = jsonMap(jsonPath);
        }

        AbaqusEmagStepVo stepVo = new AbaqusEmagStepVo();
        params.forEach((name, value) -> {
            try {
                checkParamModule(name, value);
                if (name.matches("STEP_.*")) {
                    storeEmagStep(name, value, stepVo);
                } else if (name.matches("CS_.*")) {
                    storeCoordinateSystem(name, value, stepVo);
                }
            } catch (Exception e) {
                log.info(String.format("Error Parameter: name=%s, value=%s", name, value));
            }
        });

        AbaqusEmagParam emagParam = new AbaqusEmagParam();

        emagParam.setEmagStepVo(stepVo);
        emagParam.setMeshVo(meshVo);
        emagParam.setJobVo(jobVo);
        emagParam.setPartNames(paramPart.keySet());

        if (paramPart.size() < partNum) {
            //throw new BusinessException(CodeEnum.PART_LACK);
            defaultMaterial();
        }
        List<AbaqusPartVo> parts = new ArrayList<>();
        paramPart.forEach((name, value) -> {
            parts.add(value);
        });
        emagParam.setParts(parts);

        List<InteractionVo> interactionVos = new ArrayList<>();
        interactions.forEach((name, value) -> {
            interactionVos.add(value);
        });
        emagParam.setInteractions(interactionVos);

        List<AbaqusTieVo> tieVos = new ArrayList<>();
        ties.forEach((name, value) -> {
            tieVos.add(value);
        });
        emagParam.setTieVos(tieVos);

        List<AbaqusBoundaryVo> boundaryVos = new ArrayList<>();
        boundaries.forEach((name, value) -> {
            boundaryVos.add(value);
        });
        emagParam.setBoundaryVos(boundaryVos);

        emagParam.setStpPath(stpPath.toString());
        emagParam.setStpName(stpName);
        emagParam.setBoard(board);

        return emagParam;
    }

    /**
     * 参数列表格式化
     */
    private void formattingResolver() {
        paramPart.clear();
        partNum = 0;
        meshVo = new AbaqusMeshVo();
        jobVo = new AbaqusJobVo();
        interactions.clear();
        fields.clear();
        materials.clear();
        defaultMaterial = "";
        boundaries.clear();
        bodyHeatFluxes.clear();
        ties.clear();
        initTemperature.setLength(0);
        stpPath.setLength(0);
        stpName = "";
        board = "";
        freq.clear();
        directDamping.clear();
        spectrumDensity.clear();
        frequency.clear();
    }

    private void checkParamModule(String name, Object value) {
        if (name.matches("PART_\\d+")) {
            storePart(name, value);
        } else if (name.matches("ZPARAM_PART_.*")) {
            //storePartParam(name, value);
        } else if (name.matches("MATERIAL_\\d+")) {
            storeMaterial(value);
        } else if (name.matches("ZPARAM_MATERIAL_.*")) {
            storeMaterialParam(name, value);
        } else if (name.matches("INTERACTION_\\d+")) {
            storeInteraction(value);
        } else if (name.matches("ZPARAM_INTERACTION_.*")) {
            storeInteractionParam(name, value);
        } else if (name.matches("FIELD_\\d+")) {
            storeField(value);
        } else if (name.matches("ZPARAM_FIELD_.*")) {
            storeFieldParam(name, value);
        } else if (name.matches("BOUNDARY_\\d+")) {
            storeBoundary(value);
        } else if (name.matches("ZPARAM_BOUNDARY_.*")) {
            storeBoundaryParam(name, value);
        } else if (name.matches("TIE_\\d+")) {
            storeTie(value);
        } else if (name.matches("ZPARAM_TIE_.*")) {
            storeTieParam(name, value);
        } else if (name.matches("HEATFLUX_\\d+")) {
            storeHeatFlux(value);
        } else if (name.matches("ZPARAM_HEATFLUX_.*")) {
            storeHeatFluxParam(name, value);
        } else if (name.matches("INITTEMPERATURE\\d+")) {
            if (checkValue(String.valueOf(value))) {
                throw new BusinessException(CodeEnum.DATA_TYPE_ERROR);
            }
            initTemperature.append(value);
        } else if (name.matches("MESH_.*")) {
            storeMesh(name, value);
        } else if (name.matches("JOB_.*")) {
            storeJob(name, value);
        } else if ("PATH_stpPath".equals(name)) {
            String downloadPath = String.valueOf(value);
            String[] stpPathArr = downloadPath.split("/");
            //stpName = stpPathArr[stpPathArr.length - 1];
            //stpName = stpName.split("\\.")[0] + IdUtil.fastSimpleUUID() + ".stp";
            stpName = IdUtil.fastSimpleUUID() + ".stp";
            stpPath.append(stpDir).append(stpName);
            OkHttpUtil.download(downloadPath, stpPath.toString());
        } else if ("partNum".equals(name)) {
            partNum = Integer.valueOf(String.valueOf(value));
        } else if ("ZPARAM_BOARD_board1_partname".equals(name)) {
            board = (String) value;
        }
    }

    /**
     * 获取参数Map
     *
     * @param jsonPath
     * @return
     */
    private Map<String, Object> jsonMap(String jsonPath) {
        Map<String, Object> params = JSONUtil.readJSONObject(new File(jsonPath), StandardCharsets.UTF_8);
        return params;
    }

    /**
     * 部件板块，读取部件名称，如果part中不存在部件，则创建新部件添加
     *
     * @param name  json的key
     * @param value json的value
     */
    private void storePart(String name, Object value) {
        if (!paramPart.containsKey(value)) {
            AbaqusPartVo partVo = new AbaqusPartVo();
            partVo.setName((String) value);
            paramPart.put(partVo.getName(), partVo);
        }
    }

    private void storePart(String partName) {
        if (!paramPart.containsKey(partName)) {
            AbaqusPartVo partVo = new AbaqusPartVo();
            partVo.setName(partName);
            paramPart.put(partVo.getName(), partVo);
        }
    }

    /**
     * 部件参数板块：获取部件的坐标和材料名称
     *
     * @param name  json的key
     * @param value json的value
     */
    private void storePartParam(String name, Object value) {
        String[] params = name.split("_");
        AbaqusPartVo partVo = paramPart.get(params[2]);
        if ("coordinate".equals(params[3])) {

            partVo.setCoordinate(coordinate(value));
        } else if ("material".equals(params[3])) {
            materials.putIfAbsent((String) value, new HashMap<>());
            partVo.setMaterialName((String) value);
            partVo.setMaterials(materials.get(partVo.getMaterialName()));
        }
    }

    private void storePartParam(String partName, String materialName, Object value) {
        AbaqusPartVo partVo = paramPart.get(partName);
        partVo.setCoordinate(coordinate(value));
        partVo.setMaterialName(materialName);
        partVo.setMaterials(materials.get(partVo.getMaterialName()));
    }


    /**
     * 材料板块：获取材料名称所对应的属性名称和属性值
     *
     * @param name  json的key
     * @param value json的value
     */
    private void storeMaterial(Object value) {
        materials.putIfAbsent((String) value, new HashMap<>());
    }

    private void storeMaterialParam(String name, Object value) {
        String[] params = name.split("_");
        String key = params[3];
        if ("coordinate".equals(key)) {
            storePart(params[4]);
            storePartParam(params[4], params[2], value);
        } else if ("checkAllMesh".equals(key) && (Boolean) value) {
            defaultMaterial = params[2];
        } else if (!"partname".equals(key)) {
            Map<String, List<List<String>>> material = materials.get(params[2]);
            if ((String.valueOf(value)).startsWith("[")) {
                if ("Elastic".equals(key)) {

                }
                material.put(key, jsonParseToDDArray(String.valueOf(value)));
            } else {
                List<List<String>> materialValues = new ArrayList<>();
                List<String> materialValue = new ArrayList<>();
                if (checkValue(String.valueOf(value))) {
                    throw new BusinessException(CodeEnum.DATA_TYPE_ERROR);
                }
                materialValue.add(String.valueOf(value));
                materialValues.add(materialValue);
                material.put(key, materialValues);
            }
            materials.put(params[2], material);

        }
    }

    /**
     * 分析步板块：获取分析步的各个参数
     *
     * @param name   json的key
     * @param value  json的value
     * @param stepVo 用于存放分析步参数
     */
    private void storeHeatTransferStep(String name, Object value, AbaqusHeatTransferStepVo stepVo) {
        if (checkValue(String.valueOf(value))) {
            throw new BusinessException(CodeEnum.DATA_TYPE_ERROR);
        }
        if (name.endsWith("timePeriod")) {
            stepVo.setTimePeriod((String) value);
        } else if (name.endsWith("initialInc")) {
            stepVo.setInitialInc((String) value);
        } else if (name.endsWith("minInc")) {
            stepVo.setMinInc((String) value);
        } else if (name.endsWith("maxInc")) {
            stepVo.setMaxInc((String) value);
        } else if (name.endsWith("deltmx")) {
            stepVo.setDelmx((String) value);
        }
    }


    private void storeRandomVibrationStep(String name, Object value, AbaqusRandomVibrationStepVo stepVo) {
        if (name.endsWith("dof")) {
            stepVo.setDof((String) value);
            return;
        } else if (name.endsWith("spectrumDensity")) {
            spectrumDensity = jsonParseToArray(value);
            return;
        } else if (name.endsWith("frequency")) {
            frequency = jsonParseToArray(value);
            if (checkFrequency(frequency)) {
                throw new BusinessException(CodeEnum.DATA_OUT_OF_ORDER);
            }
            return;
        }
        if (checkValue(String.valueOf(value))) {
            throw new BusinessException(CodeEnum.DATA_TYPE_ERROR);
        }
        if (name.endsWith("numEigen")) {
            stepVo.setNumEigen((String) value);
        } else if (name.endsWith("referenceGravityAcceleration")) {
            stepVo.setReferenceGravityAcceleration((String) value);
        } else if (name.endsWith("lowerFreq")) {
            freq.add((String) value);
        } else if (name.endsWith("upperFreq")) {
            freq.add((String) value);
        } else if (name.endsWith("numPoint")) {
            freq.add((String) value);
        } else if (name.endsWith("Bias")) {
            freq.add((String) value);
        } else if (name.endsWith("startMode")) {
            directDamping.add((String) value);
        } else if (name.endsWith("endMode")) {
            directDamping.add((String) value);
        } else if (name.endsWith("dampFrac")) {
            directDamping.add((String) value);
        }
    }

    private String createData() {
        StringBuilder builder = new StringBuilder();
        builder.append("(");
        int n = spectrumDensity.size();
        if (n != frequency.size()) {
            throw new BusinessException(CodeEnum.DATA_TYPE_ERROR);
        }
        for (int i = 0; i < n; i++) {
            String s = spectrumDensity.get(i).toString();
            String f = frequency.get(i).toString();
            if (checkValue(s) || checkValue(f)) {
                throw new BusinessException(CodeEnum.DATA_TYPE_ERROR);
            }
            builder.append("(").append(s).append(",0.0,").append(f).append("),");
        }
        builder.deleteCharAt(builder.length() - 1);
        builder.append(")");
        return builder.toString();
    }

    private String createData2() {
        StringBuilder builder = new StringBuilder();
        builder.append("(");
        int n = spectrumDensity.size();
        if (n != frequency.size()) {
            throw new BusinessException(CodeEnum.DATA_TYPE_ERROR);
        }
        for (int i = 0; i < n; i++) {
            String s = spectrumDensity.get(i).toString();
            String f = frequency.get(i).toString();
            if (checkValue(s) || checkValue(f)) {
                throw new BusinessException(CodeEnum.DATA_TYPE_ERROR);
            }
            builder.append("(").append(s).append(",").append(f).append("),");
        }
        builder.deleteCharAt(builder.length() - 1);
        builder.append(")");
        return builder.toString();
    }


    private void storeCoupledThermalElectricStep(String name, Object value, AbaqusCoupledThermalElectricStepVo stepVo) {
        if (checkValue(String.valueOf(value))) {
            throw new BusinessException(CodeEnum.DATA_TYPE_ERROR);
        }
        if (name.endsWith("initialInc")) {
            stepVo.setInitialInc((String) value);
        }
    }

    private void storeCoupledTempDisplacementStep(String name, Object value, AbaqusCoupledTempDisplacementStepVo stepVo) {
        if (checkValue(String.valueOf(value))) {
            throw new BusinessException(CodeEnum.DATA_TYPE_ERROR);
        }
        if (name.endsWith("timePeriod")) {
            stepVo.setTimePeriod((String) value);
        } else if (name.endsWith("initialInc")) {
            stepVo.setInitialInc((String) value);
        } else if (name.endsWith("minInc")) {
            stepVo.setMinInc((String) value);
        } else if (name.endsWith("maxInc")) {
            stepVo.setMaxInc((String) value);
        } else if (name.endsWith("deltmx")) {
            stepVo.setDelmx((String) value);
        } else if (name.endsWith("maxNumInc")) {
            stepVo.setMaxNumInc((String) value);
        }
    }

    private void storeEmagStep(String name, Object value, AbaqusEmagStepVo stepVo) {
        if (checkValue(String.valueOf(value))) {
            throw new BusinessException(CodeEnum.DATA_TYPE_ERROR);
        }
        if (name.endsWith("upperFrequency")) {
            stepVo.setUpperFrequency((String) value);
        } else if (name.endsWith("lowerFrequency")) {
            stepVo.setLowerFrequency((String) value);
        } else if (name.endsWith("numEigen")) {
            stepVo.setNumEigen((String) value);
        }
    }

    private void storeCoordinateSystem(String name, Object value, AbaqusEmagStepVo stepVo) {
        if (name.endsWith("origin")) {
            stepVo.setOrigin(jsonParseToArray(value));
        } else if (name.endsWith("point1")) {
            stepVo.setPoint1(jsonParseToArray(value));
        } else if (name.endsWith("point2")) {
            stepVo.setPoint2(jsonParseToArray(value));
        }
    }

    /**
     * 对流换热板块：用于创建对流换热参数
     *
     * @param value        json的value，即对流换热的名称
     * @param interactions 用于存放对流换热名称和对应的对象的键值对
     */
    private void storeInteraction(Object value) {

        InteractionVo interactionVo = new InteractionVo();
        interactionVo.setInteractionName((String) value);
        interactionVo.setAmperDensity(new String[6]);
        interactions.put(interactionVo.getInteractionName(), interactionVo);
    }

    /**
     * 对流换热参数板块：用于存储对流换热的对象，其中包含对流换热的参数
     *
     * @param name         json的key
     * @param value        json的value
     * @param interactions 用于存放对流换热名称和对应的对象的键值对
     */
    private void storeInteractionParam(String name, Object value) {
        String[] params = name.split("_");
        InteractionVo interactionVo = interactions.get(params[2]);
        String[] amperDensity = interactionVo.getAmperDensity();
        if ("partname".equals(params[3])) {
            interactionVo.setPartName((String) value);
        } else if ("coordinate".equals(params[3])) {
            interactionVo.setCoordinates(coordinate(value));
        } else if ("filmCoeff".equals(params[3])) {
            if (checkValue(String.valueOf(value))) {
                throw new BusinessException(CodeEnum.DATA_TYPE_ERROR);
            }
            interactionVo.setFilmCoeff(Float.valueOf((String) value));
        } else if ("sinkTemperature".equals(params[3])) {
            if (checkValue(String.valueOf(value))) {
                throw new BusinessException(CodeEnum.DATA_TYPE_ERROR);
            }
            interactionVo.setSinkTemperature((String) value);
        } else if ("amper1".equals(params[3])) {
            List<String> list = jsonParseToArray(value);
            amperDensity[0] = list.get(0);
            amperDensity[1] = list.get(1);
        } else if ("amper2".equals(params[3])) {
            List<String> list = jsonParseToArray(value);
            amperDensity[2] = list.get(0);
            amperDensity[3] = list.get(1);
        } else if ("amper3".equals(params[3])) {
            List<String> list = jsonParseToArray(value);
            amperDensity[4] = list.get(0);
            amperDensity[5] = list.get(1);
        }
    }


    /**
     * 温度场板块：用于创建温度场参数
     *
     * @param value  json的value，即温度场的名称
     * @param fields 用于存放温度场名称和对应的对象的键值对
     */
    private void storeField(Object value) {
        TemperatureFieldVo fieldVo = new TemperatureFieldVo();
        fieldVo.setFieldName((String) value);
        fields.put(fieldVo.getFieldName(), fieldVo);
    }


    /**
     * 温度场参数板块：用于存储对流换热的对象，其中包含对流换热的参数
     *
     * @param name   json的key
     * @param value  json的value
     * @param fields 用于存放温度场名称和对应的对象的键值对
     */
    private void storeFieldParam(String name, Object value) {
        String[] params = name.split("_");
        TemperatureFieldVo fieldVo = fields.get(params[2]);
        if ("partname".equals(params[3])) {
            fieldVo.setPartName((String) value);
        } else if ("coordinate".equals(params[3])) {
            fieldVo.setCoordinates(coordinate(value));
        } else if ("temperature".equals(params[3])) {
            if (checkValue(String.valueOf(value))) {
                throw new BusinessException(CodeEnum.DATA_TYPE_ERROR);
            }
            fieldVo.setTemperature(Float.valueOf((String) value));
        }
    }

    /**
     * 边界参数板块：用于创建边界参数
     *
     * @param value
     * @param boundaries
     */
    private void storeBoundary(Object value) {
        AbaqusBoundaryVo boundary = new AbaqusBoundaryVo();
        boundary.setBoundaryName((String) value);
        boundaries.put(boundary.getBoundaryName(), boundary);
    }

    /**
     * 边界参数板块：用于存储边界的对象，其中包含边界的参数
     *
     * @param name
     * @param value
     * @param boundaries
     */
    private void storeBoundaryParam(String name, Object value) {
        String[] params = name.split("_");
        AbaqusBoundaryVo boundaryVo = boundaries.get(params[2]);
        if ("partname".equals(params[3])) {
            boundaryVo.setPartName((String) value);
        } else if ("coordinate".equals(params[3])) {
            boundaryVo.setCoordinate(coordinate(value));
        } else if ("magnitude".equals(params[3])) {
            if (checkValue(String.valueOf(value))) {
                throw new BusinessException(CodeEnum.DATA_TYPE_ERROR);
            }
            boundaryVo.setMagnitude(Float.valueOf((String) value));
        } else if ("magnetic".equals(params[3])) {
            boundaryVo.setMagneticVectorPotential(jsonParseToArray(value));
        }
    }

    /**
     * 绑定参数板块：用于创建绑定参数
     *
     * @param value
     * @param ties
     */
    private void storeTie(Object value) {
        AbaqusTieVo tie = new AbaqusTieVo();
        tie.setTieName((String) value);
        ties.put(tie.getTieName(), tie);
    }

    /**
     * 绑定参数板块：用于存储绑定的对象，其中包含绑定的参数
     *
     * @param name
     * @param value
     * @param ties
     */
    private void storeTieParam(String name, Object value) {
        String[] params = name.split("_");
        AbaqusTieVo tieVo = ties.get(params[2]);
        if ("faces1Instances".equals(params[3])) {
            tieVo.setFaces1Instances((String) value);
        } else if ("face1Coordinate".equals(params[3])) {
            tieVo.setFace1Coordinate(coordinate(value));
        } else if ("faces1".equals(params[3])) {
            tieVo.setFaces1((String) value);
        } else if ("faces2".equals(params[3])) {
            tieVo.setFaces2((String) value);
        } else if ("faces2Instances".equals(params[3])) {
            tieVo.setFaces2Instances((String) value);
        } else if ("face2Coordinate".equals(params[3])) {
            tieVo.setFace2Coordinate(coordinate(value));
        }
    }

    /**
     * 热通量参数板块：用于创建热通量参数
     *
     * @param value
     * @param bodyHeatFluxes
     */
    private void storeHeatFlux(Object value) {
        AbaqusBodyHeatFluxVo heatFlux = new AbaqusBodyHeatFluxVo();
        heatFlux.setHeatFluxName((String) value);
        bodyHeatFluxes.put(heatFlux.getHeatFluxName(), heatFlux);
    }

    private void storeHeatFluxParam(String name, Object value) {
        String[] params = name.split("_");
        AbaqusBodyHeatFluxVo heatFluxVo = bodyHeatFluxes.get(params[2]);
        if ("partname".equals(params[3])) {
            heatFluxVo.setPartName((String) value);
        } else if ("coordinate".equals(params[3])) {
            heatFluxVo.setCoordinates(coordinate(value));
        } else if ("magnitude".equals(params[3])) {
            if (checkValue(String.valueOf(value))) {
                throw new BusinessException(CodeEnum.DATA_TYPE_ERROR);
            }
            heatFluxVo.setMagnitude(Float.valueOf((String) value));
        }
    }

    /**
     * 网格板块：获取网格的各个参数
     *
     * @param name   json的key
     * @param value  json的value
     * @param meshVo 用于存放网格参数
     */
    private void storeMesh(String name, Object value) {
        if (checkValue(String.valueOf(value))) {
            throw new BusinessException(CodeEnum.DATA_TYPE_ERROR);
        }
        if (name.endsWith("size")) {
            meshVo.setSize((String) value);
        } else if (name.endsWith("deviation")) {
            meshVo.setDeviationFactor((String) value);
        } else if (name.endsWith("minSizeFactor")) {
            meshVo.setMinSizeFactor((String) value);
        }
    }


    /**
     * 作业板块：获取作业的各个参数
     *
     * @param name  json的key
     * @param value json的value
     * @param jobVo 用于存放作业参数
     */
    private void storeJob(String name, Object value) {
        if (name.endsWith("name")) {
            jobVo.setJobName((String) value);
        } else if (name.endsWith("numCpus")) {
            if (checkValue(String.valueOf(value))) {
                throw new BusinessException(CodeEnum.DATA_TYPE_ERROR);
            }
            jobVo.setNumCpus(Integer.valueOf((String) value));
        } else if (name.endsWith("numDomain")) {
            if (checkValue(String.valueOf(value))) {
                throw new BusinessException(CodeEnum.DATA_TYPE_ERROR);
            }
            jobVo.setNumDomain(Integer.valueOf((String) value));
        } else if (name.endsWith("numGpus")) {
            if (checkValue(String.valueOf(value))) {
                throw new BusinessException(CodeEnum.DATA_TYPE_ERROR);
            }
            jobVo.setNumGpus(Integer.valueOf((String) value));
        }
    }

//    private static AbaqusHeatTransferParam storeAbaqusHeatTransferParam() {
//        AbaqusHeatTransferParam abaqusHeatTransferParam = new AbaqusHeatTransferParam();
//        abaqusHeatTransferParam.setMeshVo(meshVo);
//        abaqusHeatTransferParam.setJobVo(jobVo);
//        abaqusHeatTransferParam.setHeatTransferStepVo(stepVo);
//
//        abaqusHeatTransferParam.setPartNames(paramPart.keySet());
//
//        List<AbaqusPartVo> parts = new ArrayList<>();
//        paramPart.forEach((name, value) -> {
//            parts.add(value);
//        });
//        abaqusHeatTransferParam.setParts(parts);
//
//        List<InteractionVo> interactionVos = new ArrayList<>();
//        interactions.forEach((name, value) -> {
//            interactionVos.add(value);
//        });
//        abaqusHeatTransferParam.setInteractions(interactionVos);
//
//        List<TemperatureFieldVo> fieldVos = new ArrayList<>();
//        fields.forEach((name, value) -> {
//            fieldVos.add(value);
//        });
//        abaqusHeatTransferParam.setTemperatureFieldVos(fieldVos);
//
//        return null;
//    }

    /**
     * 把json文件中的内容读取成一个字符串
     *
     * @param jsonFile
     * @return
     */
    private static String getStr(File jsonFile) {
        String jsonStr = "";
        try {
            FileReader fileReader = new FileReader(jsonFile);
            Reader reader = new InputStreamReader(new FileInputStream(jsonFile), "utf-8");
            int ch = 0;
            StringBuffer sb = new StringBuffer();
            while ((ch = reader.read()) != -1) {
                sb.append((char) ch);
            }
            fileReader.close();
            reader.close();
            jsonStr = sb.toString();
            return jsonStr;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
     * 将json转换为二维数组
     *
     * @param str
     * @return
     */
    private List<List<String>> jsonParseToDDArray(String str) {
        JSONArray array = JSONUtil.parseArray(str);
        List<List<String>> ddArrays = new ArrayList<>();
        if (array == null || array.size() == 0) {
            throw new BusinessException(CodeEnum.LIST_NULL);
        }
        if (array.get(0) instanceof JSONArray) {
            for (Object o : array) {
                List<String> ddArray = new ArrayList<>();
                JSONArray inneis = (JSONArray) o;
                for (int j = 0; j < inneis.size(); j++) {
                    if (checkValue(String.valueOf(inneis.get(j)))) {
                        throw new BusinessException(CodeEnum.DATA_TYPE_ERROR);
                    }
                    ddArray.add(String.valueOf(inneis.get(j)));
                }
                ddArrays.add(ddArray);
            }
        } else {
            List<String> arrays = new ArrayList<>();
            for (Object o : array) {
                String s = String.valueOf(o);
                if (checkValue(s)) {
                    throw new BusinessException(CodeEnum.DATA_TYPE_ERROR);
                }
                arrays.add(s);
            }
            ddArrays.add(arrays);
        }
//        for (Object o : array) {
//            if (o instanceof JSONArray) {
//                List<String> ddArray = new ArrayList<>();
//                JSONArray inneis = (JSONArray) o;
//                for (int j = 0; j < inneis.size(); j++) {
//                    if (checkValue(String.valueOf(inneis.get(j)))) {
//                        throw new BusinessException(CodeEnum.DATA_TYPE_ERROR);
//                    }
//                    ddArray.add(String.valueOf(inneis.get(j)));
//                }
//                ddArrays.add(ddArray);
//            } else {
//                List<String> arrays = new ArrayList<>();
//                String s = String.valueOf(o);
//                if (checkValue(s)) {
//                    throw new BusinessException(CodeEnum.DATA_TYPE_ERROR);
//                }
//                arrays.add(s);
//                ddArrays.add(arrays);
//            }
//        }
        return ddArrays;
    }

    /**
     * 将json转换为一维数组
     *
     * @param value
     * @return
     */
    private List<String> jsonParseToArray(Object value) {
        JSONArray list = JSONUtil.parseArray(value);
        List<String> res = new ArrayList<>();
        for (Object o : list) {
            res.add(String.valueOf(o));
        }
        return res;
    }

    /**
     * json转换为列表，并拼接成固定格式的字符串
     *
     * @param list
     * @return
     */
    private String listToString(List<String> list) {
        StringBuilder builder = new StringBuilder();
        builder.append("((");
        for (String s : list) {
            builder.append(s).append(",");
        }
        builder.deleteCharAt(builder.length() - 1);
        builder.append("), )");
        return builder.toString();
    }

    /**
     * 验证数据是否为整数类型 小数类型 科学计数法类型
     *
     * @param value
     * @return 如果不为上述类型，返回true，否则返回false
     */
    private boolean checkValue(String value) {
        return !value.matches("[+-]?[0-9]+(\\.[0-9]+)?(e[+-]?[0-9]+)?");
    }

    /**
     * 验证frequency是否为升序排列
     *
     * @param frequency
     * @return 若不为升序排列，返回true，抛出异常
     */
    private boolean checkFrequency(List<String> frequency) {
        if (frequency == null || frequency.size() == 0) {
            throw new BusinessException(CodeEnum.DATA_TYPE_ERROR);
        }
        BigDecimal s0 = new BigDecimal(frequency.get(0));
        int size = frequency.size();
        for (int i = 1; i < size; i++) {
            BigDecimal s1 = new BigDecimal(frequency.get(0));
            if (s0.compareTo(s1) > 0) {
                return true;
            }
            s0 = s1;
        }
        return false;
    }

    /**
     * 给没有材料属性的部件赋予默认的材料属性
     */
    private void defaultMaterial() {
        Map<String, List<List<String>>> all = materials.get(defaultMaterial);
        AssertUtil.isNull(all, CodeEnum.PART_LACK);
        String materialName = "defaultMaterial";
        if (!paramPart.containsKey("COMPOUND")) {
            AbaqusPartVo partVo = new AbaqusPartVo();
            partVo.setName("COMPOUND");
            partVo.setMaterialName(materialName);
            partVo.setMaterials(all);
            paramPart.put(partVo.getName(), partVo);
        }
        for (int i = 1; i < partNum; i++) {
            String name = "COMPOUND-" + i;
            if (!paramPart.containsKey(name)) {
                AbaqusPartVo partVo = new AbaqusPartVo();
                partVo.setName(name);
                partVo.setMaterialName(materialName + String.valueOf(i));
                partVo.setMaterials(all);
                paramPart.put(partVo.getName(), partVo);
            }
        }
    }

    private List<String[]> coordinate(Object value) {
        JSONArray arr = (JSONArray) value;
        //List<float[]> coordinates = new ArrayList<>();
        List<String[]> coordinates = new ArrayList<>();
        //coordinates.add(new float[]{Float.valueOf((String) arr.get(0)), Float.valueOf((String) arr.get(1)), Float.valueOf((String) arr.get(2))});
        coordinates.add(new String[]{String.valueOf(arr.get(0)),String.valueOf(arr.get(1)),String.valueOf(arr.get(2))});
        return coordinates;
    }
}
